<template>
  <ul class="treelist">
    <li class="parent" v-if="root.children.length" v-for="root in treenodes" type="root">
      <span class="treeitem" @click.stop="toggle">
        <i v-if="root.icon" :class="root.icon"></i>
        <span>{{root.name}}</span>
        <label class="md-checkbox ml-auto">
          <input type="checkbox" name="items" :value="root.id" :checked="checked.includes(root.id)" @change="change"><i class="bg-themedark"></i> 全部
        </label>
      </span>
      <children :parent="root" :checked="checked"></children>
    </li>
    <li v-else>
      <label class="treeitem">
        <label class="md-checkbox mr-2">
          <input type="checkbox" name="items" :value="root.id" :checked="checked.includes(root.id)" @change="change"><i class="bg-themedark"></i>
        </label>
        <i v-if="root.icon" :class="root.icon"></i>
        <span>{{root.name}}</span>
      </label>
    </li>
  </ul>
</template>
<!--
  树形列表, 目前用于权限树展示 (是否还有其它用途?)
-->
<script>
  /* 获取最近的父<li>元素 */
  function closest (el) {
    var parent = el.parentNode
    if (parent.tagName === 'LI') return parent
    return closest(parent)
  }
  /* 展开/收缩子元素 */
  function toggle (e) {
    e.currentTarget.parentNode.classList.toggle('open')
  }
  /* 选中状态改变回调 */
  function change (e) {
    var checked = e.currentTarget.checked, parent = closest(e.currentTarget)
    parent.querySelectorAll('input').forEach(i => i.checked = checked) // 设置所有子节点为相同状态
    check_ancestors(parent, checked)
  }
  /* 递归设置祖先元素状态 */
  function check_ancestors (parent, checked) {
    if (parent.type == 'root') return  // 当前元素不为根元素时, 还需处理祖先节点的选中状态
    var siblings = parent.parentNode.childNodes, len = 0
    siblings.forEach(s => s.querySelector('input').checked && len++)
    parent = closest(parent)
    parent.querySelector('input').checked = siblings.length === len
    check_ancestors(parent, checked)
  }
  export default {
    name: 'treeview',
    props: {
      treenodes: Array,
      checked: {type: Array, default: () => []}
    },
    methods: {toggle, change},
    components: {
      children: {
        name: 'children',
        props: ['parent', 'checked'],
        template: `<ul>
          <li class="parent" v-if="child.children.length"  v-for="child in parent.children">
            <span class="treeitem" @click.stop="toggle">
              <i v-if="child.icon" :class="child.icon"></i>
              <span>{{child.name}}</span>
              <label class="md-checkbox ml-auto">
              <input type="checkbox" name="items" :value="child.id" :checked="checked.includes(child.id)" @change="change"><i class="bg-themedark"></i> 全部
              </label>
            </span>
            <children :parent="child" :checked="checked"></children>
          </li>
          <li v-else>
            <label class="treeitem">
              <label class="md-checkbox mr-2">
                <input type="checkbox" name="items" :value="child.id" :checked="checked.includes(child.id)" @change="change"><i class="bg-themedark"></i>
              </label>
              <i v-if="child.icon" :class="child.icon"></i>
              <span>{{child.name}}</span>
            </label>
          </li>
        </ul>`,
        methods: {toggle, change}
      }
    }
  }
</script>

<style>
  .treelist { list-style: none; padding: 0 0 1rem }
  .treelist > li:before, .treelist > li:after { display: none !important }
  .treelist ul { padding: 10px 0 10px 53px; position: relative; list-style: none; margin: 0; display: none}
  .treelist .open > ul { display: block }
  .treelist .parent > .treeitem::before { margin-right: .5rem; text-align: center; width: 1.5rem }
  .treelist .parent > .treeitem::before { font-family: themify; content: '\E65D' }
  .treelist .parent.open > .treeitem::before { content: '\E65F' }
  .treelist .parent:last-child::before { border-top: 1px solid #e2e2e2; background: #fff; height: 100% }
  .treelist ul:before { background: #e2e2e2; position: absolute; height: calc(100% - 33px); content: ''; width: 1px; left: 23px; top: -.5rem }
  .treelist li { position: relative }
  .treelist li:before,
  .treelist li:after { background: #e2e2e2; position: absolute; display: block; content: ''; top: 22px }
  .treelist li:before { height: 1px; width: 30px; left: -30px }
  .treelist li:after { border-radius: 50%; margin-top: -2px; left: -32px; height: 5px; width: 5px }
  .treelist .treeitem { display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-align-items: center; -ms-flex-align: center; align-items: center; border: 1px solid #ddd; margin-bottom: .5em; border-radius: 4px; position: relative; padding: .625rem; color: #777 }
  .treelist .treeitem > i { margin-right: .25rem; text-align: center; width: 1.1rem }
  .treelist .treeitem:hover, .treelist .treeitem:focus { text-decoration: none; background: #f6f6f6; color: #333 }
</style>